/**
 * SIX VULN - http://code.google.com/p/six-vuln/
 * Copyright (C) 2006
 *   National Institute of Advanced Industrial Science and Technology (AIST)
 *   Registration Number: H20PRO-863
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jp.go.aist.six.vuln.model.scap.vulnerability;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import jp.go.aist.six.vuln.model.scap.core.CheckReferenceType;
import jp.go.aist.six.vuln.model.scap.cpe.PlatformType;
import jp.go.aist.six.vuln.model.scap.patch.PatchType;



/**
 * A single fix action should only cover a single patch application,
 * software update, configuration change, or external fix.
 * Dependencies should be documented by using
 * the "nextFixAction" to point to a recursive list of fix actions.
 *
 * @author	Akihito Nakamura, AIST
 * @version $Id: FixActionType.java 529 2013-04-15 07:08:54Z nakamura5akihito@gmail.com $
 */
public class FixActionType
    implements Serializable
{

    private PatchType  patch;
    //{0..1}

    private VulnerabilityReferenceType  configurationRemediation;
    //{0..1}

    /**
     * CPE name of the software update package.
     */
    private final Collection<String>  softwareUpdate = new ArrayList<String>();
    //{0..*, scap-core:cpeNamePatternType}


    private final Collection<String>  notes = new ArrayList<String>();
    //{0..*}

    private final Collection<String>  deprecatedBy = new ArrayList<String>();
    //{0..*, scap-core:CpeNamePatternType}

    private final Collection<FixActionType>  nextFixAction = new ArrayList<FixActionType>();
    //{0..*}

    private final Collection<ToolConfigurationType>  fixActionToolConfiguration = new ArrayList<ToolConfigurationType>();
    //{0..*}

    private final Collection<PlatformType>  applicableConfiguration = new ArrayList<PlatformType>();
    //{0..*}

    /**
     * States whether the fix action fully avoids the risk
     * associated with the vulnerability or reduces risk to some extent.
     */
    private FixEffectivenessEnumType  effectiveness;
    //{0..1}

    /**
     * Describes or points to the check/test (either OVAL or other)
     * that this particular fix action addresses.
     * E.G. applying this fix will change the value of this test result.
     */
    private final Collection<CheckReferenceType>  applicableCheck = new ArrayList<CheckReferenceType>();
    //{0..*}

    private FixActionDescriptionEnumType  fixActionDescription;
    //{required}

    private FixActionTypeEnumType  fixActionType;
    //{required}

    /**
     * Unique value within the source.
     * Will be used with the source element to serve as a global unique identifier.
     */
    private String  id;
    //{xsd:token, required}

    /**
     * Should be a URI-like -- e.g. inverted DNS address e.g mil.jtf-gno.
     */
    private String  source;
    //{xsd:anyURI, required}



    /**
     */
    public FixActionType()
    {
    }



    /**
     */
    public PatchType getPatch()
    {
        return patch;
    }


    public void setPatch(
                    final PatchType patch
                    )
    {
        this.patch = patch;
    }



    /**
     */
    public VulnerabilityReferenceType getConfigurationRemediation()
    {
        return configurationRemediation;
    }

    public void setConfigurationRemediation(
                    final VulnerabilityReferenceType configurationRemediation
                    )
    {
        this.configurationRemediation = configurationRemediation;
    }



    /**
     */
    public Collection<String> getSoftwareUpdate()
    {
        return softwareUpdate;
    }


    public void setSoftwareUpdate(
                    final Collection<String> softwareUpdate_list
                    )
    {
        if (softwareUpdate_list != softwareUpdate) {
            softwareUpdate.clear();
            if (softwareUpdate_list != null) {
                softwareUpdate.addAll( softwareUpdate_list );
            }
        }
    }



    /**
     */
    public Collection<String> getNotes()
    {
        return notes;
    }


    public void setNotes(
                    final Collection<String> notes_list
                    )
    {
        if (notes_list != notes) {
            notes.clear();
            if (notes_list != null) {
                notes.addAll( notes_list );
            }
        }
    }



    /**
     */
    public Collection<String> getDeprecatedBy()
    {
        return deprecatedBy;
    }


    public void setDeprecatedBy(
                    final Collection<String> deprecatedBy_list
                    )
    {
        if (deprecatedBy_list != deprecatedBy) {
            deprecatedBy.clear();
            if (deprecatedBy_list != null) {
                deprecatedBy.addAll( deprecatedBy_list );
            }
        }
    }



    /**
     */
    public Collection<FixActionType> getNextFixAction()
    {
        return nextFixAction;
    }


    public void setNextFixAction(
                    final Collection<? extends FixActionType> nextFixAction_list
                    )
    {
        if (nextFixAction_list != nextFixAction) {
            nextFixAction.clear();
            if (nextFixAction_list != null) {
                nextFixAction.addAll( nextFixAction_list );
            }
        }
    }



    /**
     */
    public Collection<ToolConfigurationType> getFixActionToolConfiguration()
    {
        return fixActionToolConfiguration;
    }


    public void setFixActionToolConfiguration(
                    final Collection<? extends ToolConfigurationType> fixActionToolConfiguration_list
                    )
    {
        if (fixActionToolConfiguration_list != fixActionToolConfiguration) {
            fixActionToolConfiguration.clear();
            if (fixActionToolConfiguration_list != null) {
                fixActionToolConfiguration.addAll( fixActionToolConfiguration_list );
            }
        }
    }



    /**
     */
    public Collection<PlatformType> getApplicableConfiguration()
    {
        return applicableConfiguration;
    }


    public void setApplicableConfiguration(
                    final Collection<? extends PlatformType> applicableConfiguration_list
                    )
    {
        if (applicableConfiguration_list != applicableConfiguration) {
            applicableConfiguration.clear();
            if (applicableConfiguration_list != null) {
                applicableConfiguration.addAll( applicableConfiguration_list );
            }
        }
    }



    /**
     */
    public FixEffectivenessEnumType getEffectiveness()
    {
        return effectiveness;
    }


    public void setEffectiveness(
                    final FixEffectivenessEnumType effectiveness
                    )
    {
        this.effectiveness = effectiveness;
    }



    /**
     */
    public Collection<CheckReferenceType> getApplicableCheck()
    {
        return applicableCheck;
    }


    public void setApplicableCheck(
                    final Collection<? extends CheckReferenceType> applicableCheck_list
                    )
    {
        if (applicableCheck_list != applicableCheck) {
            applicableCheck.clear();
            if (applicableCheck_list != null) {
                applicableCheck.addAll( applicableCheck_list );
            }
        }
    }



    /**
     */
    public FixActionDescriptionEnumType getFixActionDescription()
    {
        return fixActionDescription;
    }


    public void setFixActionDescription(
                    final FixActionDescriptionEnumType fixActionDescription
                    )
    {
        this.fixActionDescription = fixActionDescription;
    }



    /**
     */
    public FixActionTypeEnumType getFixActionType()
    {
        return fixActionType;
    }


    public void setFixActionType(
                    final FixActionTypeEnumType fixActionType
                    )
    {
        this.fixActionType = fixActionType;
    }



    /**
     */
    public String getId()
    {
        return id;
    }


    public void setId(
                    final String id
                    )
    {
        this.id = id;
    }



    /**
     */
    public String getSource()
    {
        return source;
    }


    public void setSource(
                    final String source
                    )
    {
        this.source = source;
    }



    //*********************************************************************
    //  java.lang.Object
    //*********************************************************************

    @Override
    public int hashCode()
    {
        final int prime = 37;
        int result = 17;

        final PatchType  patch = getPatch();
        final VulnerabilityReferenceType  configurationRemediation = getConfigurationRemediation();
        final Collection<String>  softwareUpdate = getSoftwareUpdate();
        final Collection<String>  notes = getNotes();
        final Collection<String>  deprecatedBy = getDeprecatedBy();
        final Collection<FixActionType>  nextFixAction = getNextFixAction();
        final Collection<ToolConfigurationType>  fixActionToolConfiguration = getFixActionToolConfiguration();
        final Collection<PlatformType>  applicableConfiguration = getApplicableConfiguration();
        final FixEffectivenessEnumType  effectiveness = getEffectiveness();
        final Collection<CheckReferenceType>  applicableCheck = getApplicableCheck();
        final FixActionDescriptionEnumType  fixActionDescription = getFixActionDescription();
        final FixActionTypeEnumType  fixActionType = getFixActionType();
        final String  id = getId();
        final String  source = getSource();

        result = prime * result + ((patch == null) ? 0 : patch.hashCode());
        result = prime * result + ((configurationRemediation == null) ? 0 : configurationRemediation.hashCode());
        result = prime * result + ((softwareUpdate == null) ? 0 : softwareUpdate.hashCode());
        result = prime * result + ((notes == null) ? 0 : notes.hashCode());
        result = prime * result + ((deprecatedBy == null) ? 0 : deprecatedBy.hashCode());
        result = prime * result + ((nextFixAction == null) ? 0 : nextFixAction.hashCode());
        result = prime * result + ((fixActionToolConfiguration == null) ? 0 : fixActionToolConfiguration.hashCode());
        result = prime * result + ((applicableConfiguration == null) ? 0 : applicableConfiguration.hashCode());
        result = prime * result + ((effectiveness == null) ? 0 : effectiveness.hashCode());
        result = prime * result + ((applicableCheck == null) ? 0 : applicableCheck.hashCode());
        result = prime * result + ((fixActionDescription == null) ? 0 : fixActionDescription.hashCode());
        result = prime * result + ((fixActionType == null) ? 0 : fixActionType.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((source == null) ? 0 : source.hashCode());

        return result;
    }



    @Override
    public boolean equals(
                    final Object obj
                    )
    {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof FixActionType)) {
            return false;
        }

        FixActionType  other = (FixActionType)obj;

        final PatchType   this_patch =  this.getPatch();
        final PatchType  other_patch = other.getPatch();
        if (this_patch == other_patch
                        ||  (this_patch != null  &&  this_patch.equals( other_patch ))) {
            final VulnerabilityReferenceType   this_configurationRemediation =  this.getConfigurationRemediation();
            final VulnerabilityReferenceType  other_configurationRemediation = other.getConfigurationRemediation();
            if (this_configurationRemediation == other_configurationRemediation
                            ||  (this_configurationRemediation != null  &&  this_configurationRemediation.equals( other_configurationRemediation ))) {
                final Collection<String>   this_softwareUpdate =  this.getSoftwareUpdate();
                final Collection<String>  other_softwareUpdate = other.getSoftwareUpdate();
                if (this_softwareUpdate == other_softwareUpdate
                                ||  (this_softwareUpdate != null  &&  other_softwareUpdate != null
                                &&  this_softwareUpdate.size() == other_softwareUpdate.size()
                                &&  this_softwareUpdate.containsAll( other_softwareUpdate ))) {
                    final Collection<String>   this_notes =  this.getNotes();
                    final Collection<String>  other_notes = other.getNotes();
                    if (this_notes == other_notes
                                    ||  (this_notes != null  &&  other_notes != null
                                    &&  this_notes.size() == other_notes.size()
                                    &&  this_notes.containsAll( other_notes ))) {
                        final Collection<String>   this_deprecatedBy =  this.getDeprecatedBy();
                        final Collection<String>  other_deprecatedBy = other.getDeprecatedBy();
                        if (this_deprecatedBy == other_deprecatedBy
                                        ||  (this_deprecatedBy != null  &&  other_deprecatedBy != null
                                        &&  this_deprecatedBy.size() == other_deprecatedBy.size()
                                        &&  this_deprecatedBy.containsAll( other_deprecatedBy ))) {
                            final Collection<FixActionType>   this_nextFixAction =  this.getNextFixAction();
                            final Collection<FixActionType>  other_nextFixAction = other.getNextFixAction();
                            if (this_nextFixAction == other_nextFixAction
                                            ||  (this_nextFixAction != null  &&  other_nextFixAction != null
                                            &&  this_nextFixAction.size() == other_nextFixAction.size()
                                            &&  this_nextFixAction.containsAll( other_nextFixAction ))) {
                                final Collection<ToolConfigurationType>   this_fixActionToolConfiguration =  this.getFixActionToolConfiguration();
                                final Collection<ToolConfigurationType>  other_fixActionToolConfiguration = other.getFixActionToolConfiguration();
                                if (this_fixActionToolConfiguration == other_fixActionToolConfiguration
                                                ||  (this_fixActionToolConfiguration != null  &&  other_fixActionToolConfiguration != null
                                                &&  this_fixActionToolConfiguration.size() == other_fixActionToolConfiguration.size()
                                                &&  this_fixActionToolConfiguration.containsAll( other_fixActionToolConfiguration ))) {
                                    final Collection<PlatformType>   this_applicableConfiguration =  this.getApplicableConfiguration();
                                    final Collection<PlatformType>  other_applicableConfiguration = other.getApplicableConfiguration();
                                    if (this_applicableConfiguration == other_applicableConfiguration
                                                    ||  (this_applicableConfiguration != null  &&  other_applicableConfiguration != null
                                                    &&  this_applicableConfiguration.size() == other_applicableConfiguration.size()
                                                    &&  this_applicableConfiguration.containsAll( other_applicableConfiguration ))) {
                                        if (this.getEffectiveness() == other.getEffectiveness()) {
                                            final Collection<CheckReferenceType>   this_applicableCheck =  this.getApplicableCheck();
                                            final Collection<CheckReferenceType>  other_applicableCheck = other.getApplicableCheck();
                                            if (this_applicableCheck == other_applicableCheck
                                                            ||  (this_applicableCheck != null  &&  other_applicableCheck != null
                                                            &&  this_applicableCheck.size() == other_applicableCheck.size()
                                                            &&  this_applicableCheck.containsAll( other_applicableCheck ))) {
                                                if (this.getFixActionDescription() == other.getFixActionDescription()) {
                                                    if (this.getFixActionType() == other.getFixActionType()) {
                                                        final String   this_id =  this.getId();
                                                        final String  other_id = other.getId();
                                                        if (this_id == other_id
                                                                        ||  (this_id != null  &&  this_id.equals( other_id ))) {
                                                            final String   this_source =  this.getSource();
                                                            final String  other_source = other.getSource();
                                                            if (this_source == other_source
                                                                            ||  (this_source != null  &&  this_source.equals( other_source ))) {
                                                                return true;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return false;
    }



    @Override
    public String toString()
    {
        return "FixActionType[patch="                       + getPatch()
                        + ", configurationRemediation="     + getConfigurationRemediation()
                        + ", softwareUpdate="               + getSoftwareUpdate()
                        + ", notes="                        + getNotes()
                        + ", deprecatedBy="                 + getDeprecatedBy()
                        + ", nextFixAction="                + getNextFixAction()
                        + ", fixActionToolConfiguration="   + getFixActionToolConfiguration()
                        + ", applicableConfiguration="      + getApplicableConfiguration()
                        + ", effectiveness="                + getEffectiveness()
                        + ", applicableCheck="              + getApplicableCheck()
                        + ", fixActionDescription="         + getFixActionDescription()
                        + ", fixActionType="                + getFixActionType()
                        + ", id="                           + getId()
                        + ", source="                       + getSource()
                        + "]";
    }

}
//FixActionType
